<template>
  <div>
    <el-form
      class="dialog-form"
      ref="dataForm"
      :rules="rules"
      :disabled="disabled"
      size="mini"
      :model="value"
      label-position="right"
      :label-width="labelWidth"
    >

      <lang-wrapper :lang="hasTopLang" @change="handleChangeLangId">
      </lang-wrapper>
      <div v-if="isGroupedColumns" class="form__stepArea">
        <el-steps :active="currentStep+1" align-center>
          <el-step v-for="group in columnGroupNames" :title="group" :key="group"></el-step>
        </el-steps>
      </div>
      <el-row :gutter="20" type="flex">
        <template v-for="(col,colIndex) in showedColumns">
          <el-col v-if="isShowed(col)" :key="col.prop || colIndex" :span="col.span || 12">
            <component :is="wrapElName(col)" v-bind="wrapElProp(col)">
              <lang-wrapper :lang="col.lang" :show-tab="!hasTopLang" :active-lang-id="activeLangId">
                <template v-slot="{ lang:langItem }">
                  <div class="flex flex-start">
                    <div class="flex-con">
                      <component
                        :is="elName(col)"
                        v-if="langItem"
                        v-model="value[col.prop][langItem.id]"
                        v-bind="elProps(col,langItem)"
                        v-on="elEventHandlers(col)"
                      />
                      <component
                        :is="elName(col)"
                        v-else
                        v-model="value[col.prop]"
                        v-bind="elProps(col)"
                        v-on="elEventHandlers(col)"
                      />
                    </div>
                    <div style="padding-left:4px;" v-if="col.tool">
                      <my-tool v-if="langItem" v-model="value[col.prop][langItem.id]" :options="col.tool.options"/>
                      <my-tool v-else v-model="value[col.prop]" :options="col.tool.options"/>
                    </div>
                  </div>
                </template>
              </lang-wrapper>
            </component>
          </el-col>
        </template>
      </el-row>
    </el-form>
    <div class="dialog-footer">
      <el-button
        size="mini"
        v-if="!viewMode"
        @click="handleClose"
      >取消
      </el-button>
      <template v-for="(item,itemIndex) in formButtons">
        <el-button
          :key="itemIndex"
          v-perm="item.name"
          class="filter-item"
          :type="getButtonType(item)"
          size="mini"
          @click="handleClickToolButton(item)"
        >
          {{ item.label }}
        </el-button>
      </template>
      <template v-if="formButtons.length===0">
        <el-button
          v-if="currentStep > 0"
          size="mini"
          type="primary"
          @click="handleToPrev"
        >上一步
        </el-button>
        <el-button
          v-if="isFinalStep"
          type="primary"
          size="mini"
          :loading="submitting"
          @click="submitFormAction"
        >确定
        </el-button>
        <el-button
          v-if="showContinue"
          type="primary"
          size="mini"
          :loading="submitting"
          @click="submitFormAndContinueAction"
        >提交并继续
        </el-button>
        <el-button
          v-if="!isFinalStep"
          size="mini"
          type="primary"
          @click="handleToNext"
        >下一步
        </el-button>
      </template>
    </div>
    <!--    <el-dialog :visible.sync="editorShowed" width="700px" append-to-body>-->
    <!--      <div ref="currentView">-->
    <!--      </div>-->
    <!--      <div slot="footer" class="dialog-footer">-->
    <!--        <el-button size="mini" @click="editorShowed=false">取消</el-button>-->
    <!--        <el-button size="mini" type="primary" @click="handleEditSure">确定</el-button>-->
    <!--      </div>-->
    <!--    </el-dialog>-->
  </div>

</template>

<script>
import ColumnType from '@/framework/constant/ColumnType'
import SortableUpload from '@/framework/components/SortableUpload'
import SortableUploadVideo from '@/framework/components/SortableUploadVideo'
import FormUtil from '@/framework/infra/form/FormUtil'
import Selector from '@/framework/components/Selector'
import RichEditor from '@/framework/components/RichEditor/RichEditor'
import DateType from '@/framework/constant/DateType'
import LangWrapper from '@/framework/components/lang/LangWrapper'
import RadioSelector from '@/framework/components/RadioSelector'
import Cascader from '@/framework/components/Cascader'
import FormRuleValidator from '@/framework/infra/validator/FormRuleValidator'
import LangTypeEnum from '@/framework/constant/LangTypeEnum'
import SkuEditor from '@/framework/components/sku/SkuEditor'
import SkuUtil from '@/framework/components/sku/SkuUtil'
import PlainText from '@/framework/components/PlainText'
import ColumnUtil from '@/framework/components/table/ColumnUtil'
import {mapGetters} from 'vuex'
import RouterUtil from '@/framework/infra/router/RouterUtil'
import TableButtonType from '@/framework/constant/TableButtonType'
import NameUtil from '@/framework/infra/name/NameUtil'
import DomUtil from '@/framework/infra/util/DomUtil'
import AddressSelector from '@/framework/components/AddressSelector'
import StrategyLines from '@/framework/components/StrategyLines'
import LeftTime from '@/framework/components/LeftTime'
import FormColumnRender from '@/framework/components/form/FormColumnRender'
import MultipleInput from '@/framework/components/MultipleInput'
import NbTextArea from '@/framework/components/NbTextArea'
import RichTextEditor from '@/framework/components/RichTextEditor'
import Vue from 'vue'
import TableSetting from '@/framework/components/table/TableSetting'
import MyTool from '@/framework/components/form/MyTool'
import MulSelector from '@/framework/components/MulSelector'
import VoiceUpload from '@/framework/components/VoiceUpload'


export default {
  name: 'ColumnsForm',
  components: {
    MyTool,
    FormColumnRender,
    AddressSelector,
    StrategyLines,
    PlainText,
    RadioSelector,
    LangWrapper,
    RichEditor,
    NbTextArea,
    MulSelector,
    Selector,
    SortableUpload,
    SortableUploadVideo,
    Cascader,
    SkuEditor,
    RichTextEditor,
    MultipleInput,
    LeftTime,
    VoiceUpload
  },
  data() {
    return {
      ColumnType,
      // editorShowed: false,
      activeLangId: LangTypeEnum.CNT.id,
      currentStep: this.stepIndex,
      submitting: false
    }
  },
  watch: {
    stepIndex() {
      this.currentStep = this.stepIndex
    },
    rules() {
      this.$refs.dataForm.clearValidate()
    }
  },
  computed: {
    ...mapGetters(['routes']),
    buttons() {
      return RouterUtil.getButtonsByFullPath(this.routes, this.$route.path, this.groupId) || []
    },
    isFinalStep() {
      if (!this.isGroupedColumns) {
        return true
      }
      return this.currentStep === this.columnGroupNames.length - 1
    },
    formButtons() {
      return this.buttons.filter(el => el.type === TableButtonType.FORM)
    },
    hasTopLang() {
      return this.lang && this.finalColumns.some(el => el.lang)
    },
    isGroupedColumns() {
      return ColumnUtil.isGroupColumns(this.columns)
    },
    columnGroupNames() {
      if (this.isGroupedColumns) {
        return this.columns.map(el => el.groupName)
      }
      return []
    },
    finalColumns() {
      if (this.isGroupedColumns) {
        return this.columns[this.currentStep].columns
      }
      return this.columns
    },
    showedColumns() {
      if (this.viewMode) {
        return this.finalColumns
      }
      return this.finalColumns.filter(el => !el.hiddenInForm)
    },
    rules() {
      if (this.viewMode) {
        return {}
      }
      const result = this.finalColumns.reduce((a, b) => {
        if (b.rules) {
          a[b.prop] = b.rules
        }
        if (b.required) {
          a[b.prop] = a[b.prop] || []
          let rule
          if (b.lang) {
            rule = {
              required: true,
              validator: FormRuleValidator.validateLangTextNotEmpty
            }
          } else if (b.type === ColumnType.SKU_EDITOR) {
            rule = {
              required: true,
              validator: SkuUtil.validateSkuEditor
            }
          } else {
            rule = {
              required: true,
              message: (b.type === ColumnType.SELECT || b.type === ColumnType.RADIO || b.type === ColumnType.CASCADER) ? `请选择${b.label}` : `${b.label}不能为空`
            }
            if (b.type === ColumnType.CASCADER) {
              rule.type = 'array'
            }
          }
          a[b.prop].push(rule)
        }
        return a
      }, {})
      return result
    }
  },
  props: {
    viewMode: {
      type: Boolean,
      default: false
    },
    labelWidth: {
      type: String,
      default: '140px'
    },
    columns: {
      type: Array,
      default() {
        return []
      }
    },
    groupId: {
      type: Number,
      default: 0
    },
    stepIndex: {
      type: Number,
      default: 0
    },
    isEdit: {
      type: Boolean,
      default: false
    },
    showContinue: {
      type: Boolean,
      default: false
    },
    disabled: {
      type: Boolean,
      default: false
    },
    value: {
      type: Object,
      default() {
        return {}
      }
    },
    // 顶部显示语言切换
    lang: {
      type: [Object, Boolean],
      default: false
    }
  },
  methods: {
    // registerComponent(componentName) {
    //   return componentName.then(component => {
    //     return Vue.extend(component.default)
    //   })
    // },
    handleEditSure() {
      this.editorShowed = false
    },
    handleShowEditor(col) {
      this.editorShowed = true
      col.onEditorShow && col.onEditorShow(this.value)
      // this.registerComponent(col.editor).then(Component => {
      //   console.log(this.value[col.prop])
      //   new Component({
      //     el: this.$refs.currentView,
      //     data: {
      //       value: this.value[col.prop]
      //     }
      //   })
      // })
    },
    getButtonType(item) {
      if (item.buttonType) {
        return item.buttonType
      }
      return 'primary'
    },
    handleClickToolButton(button) {
      const funcType = NameUtil.camelCase('handle', button.funcType)
      DomUtil.invokeClosetDomWithFuncName(this.$parent, funcType, {$dialog: this, arg: this.value})
    },
    handleClose() {
      this.$emit('close')
    },
    handleChangeLangId({id}) {
      this.activeLangId = id
    },
    wrapElName(col) {
      if (col.type === ColumnType.SKU_EDITOR) {
        return 'div'
      }
      return 'el-form-item'
    },
    wrapElProp(col) {
      if (col.type === ColumnType.SKU_EDITOR) {
        return {}
      }
      return {
        label: col.label,
        prop: col.prop
      }
    },
    elName(col) {
      if (this.viewMode) {
        return 'form-column-render'
      }
      if (col.type === ColumnType.MULTIPLE_TEXT) {
        return 'multiple-input'
      }
      if (col.type === ColumnType.NB_TEXTAREA) {
        return 'nb-text-area'
      }
      if (col.type === ColumnType.CHECK) {
        return 'el-checkbox'
      }
      if (col.type === ColumnType.RICH_EDITOR) {
        return 'rich-editor'
      } else if (col.type === ColumnType.PLAIN_TEXT) {
        return 'plain-text'
      } else if (col.type === ColumnType.LEFT_TIME_COUNT) {
        return 'left-time'
      } else if (col.type === ColumnType.NUMBER || col.type === ColumnType.MONEY) {
        return 'el-input-number'
      } else if (col.type === ColumnType.RICH_TEXTAREA) {
        return 'rich-text-editor'
      } else if (col.type === ColumnType.CASCADER) {
        return 'cascader'
      } else if (col.type === ColumnType.ADDRESS) {
        return 'address-selector'
      } else if (col.type === ColumnType.RADIO) {
        return 'radio-selector'
      } else if (col.type === ColumnType.MUL_SELECT) {
        return 'mul-selector'
      } else if (col.type === ColumnType.SKU_EDITOR) {
        // return 'div'
        return 'sku-editor'
      } else if (col.type === ColumnType.IMAGE) {
        return 'sortable-upload'
      } else if (col.type === ColumnType.VIDEO_FORMAT) {
        return 'sortable-upload-video'
      } else if (col.type === ColumnType.DATETIME || col.type === ColumnType.DATE) {
        return 'el-date-picker'
      } else if (col.type === ColumnType.TIME) {
        return 'el-time-select'
      } else if (col.type === ColumnType.SELECT) {
        return 'selector'
      } else if (col.type === ColumnType.BUTTON_LINE) {
        return 'strategy-lines'
      } else if (col.type === ColumnType.VOICE_UPLOAD) {
        return 'voice-upload'
      }
      if (col.autocomplete) {
        return 'el-autocomplete'
      }
      return 'el-input'
    },
    elEventHandlers(col) {
      const result = {}
      if (col.onChange || col.type === ColumnType.SELECT) {
        result.change = ({value, option}) => {
          if (col.searchCached) {
            TableSetting.saveDefaultLocalSearchParam({
              [col.prop]: value
            })
          }
          col.onChange && col.onChange({
            value,
            option,
            formData: this.value
          })
        }
      }
      return result
    },
    elProps(col, lang = null) {
      const result = {}
      let placeholder = ''
      if (col.type === ColumnType.PASSWORD) {
        result.type = 'password'
        placeholder = '请输入'
      } else if (col.type === ColumnType.IMAGE) {
        result.limit = col.limit || 1
        result.isSingle = !col.limit || col.limit === 1
        result.firstAsCover = false
      } else if (col.type === ColumnType.DATE) {
        result.type = DateType.DATE
        placeholder = '请选择'
        result.valueFormat = 'yyyy-MM-dd'
      } else if (col.type === ColumnType.NUMBER) {
        if ('precision' in col) {
          result.precision = col.precision
        }
      } else if (col.type === ColumnType.MONEY) {
        result.precision = 2
        result.min = 0
      } else if (col.type === ColumnType.PLAIN_TEXT) {
        result.column = col
      } else if (col.type === ColumnType.TIME) {
        result.column = col
        result.type = DateType.TIME
        placeholder = '请选择'
        result.pickerOptions = {
          start: '06:30',
          step: '00:15',
          end: '23:30'
        }
        result.valueFormat = 'HH:mm'
      } else if (col.type === ColumnType.DATETIME) {
        result.type = DateType.DATETIME
        placeholder = '请选择'
        result.valueFormat = 'yyyy-MM-dd HH:mm:ss'
      } else if (col.type === ColumnType.SELECT || col.type === ColumnType.RADIO || col.type === ColumnType.CASCADER || col.type === ColumnType.MUL_SELECT) {
        result.size = 'mini'
        result.clearable = true
        result.options = col.options
        placeholder = '请选择'
        if (col.type === ColumnType.CASCADER && col.props) {
          result.props = col.props
        }
      } else if (col.type === ColumnType.ADDRESS) {
        placeholder = '请选择'
      } else if(col.type === ColumnType.BUTTON_LINE) {
        result.info = this.value
      } else if (col.type === ColumnType.TEXTAREA || col.type === ColumnType.NB_TEXTAREA) {
        result.rows = col.rows || 3
        result.type = 'textarea'
        placeholder = '请输入'
      } else {
        placeholder = '请输入'
      }
      if (col.autocomplete) {
        result.fetchSuggestions = col.autocomplete
      }
      if ('readonly' in col) {
        result.readonly = this.valueFilter(col.readonly, false)
      }
      if ('disabled' in col) {
        result.disabled = this.valueFilter(col.disabled, false)
      }
      if (placeholder) {
        result.placeholder = placeholder + col.label
      }
      if (col.renderOptions) {
        Object.assign(result, col.renderOptions)
      }
      if (lang && result.placeholder) {
        result.placeholder += ` (${lang.name})`
      }
      if (col.placeholder) {
        result.placeholder = col.placeholder
      }
      result.isEdit = this.isEdit
      result.prop = col.prop
      if (this.viewMode) {
        result.column = col
      }

      return result
    },
    validate() {
      return FormUtil.validate(this.$refs.dataForm)
    },
    async submitFormAndContinueAction() {
      if (this.viewMode) {
        this.$emit('submitAndContinue', {
          data: this.value,
          done: () => {
            this.submitting = false
          }
        })
        return
      }
      if (await this.validate()) {
        this.submitting = true
        this.$emit('submitAndContinue', {
          data: this.value,
          done: () => {
            this.submitting = false
          }
        })
      }
    },
    async submitFormAction() {
      if (this.viewMode) {
        this.$emit('submit', {
          data: this.value,
          done: () => {
            this.submitting = false
          }
        })
        return
      }
      if (await this.validate()) {
        this.submitting = true
        this.$emit('submit', {
          data: this.value,
          done: () => {
            this.submitting = false
          }
        })
      }
    },
    handleToPrev() {
      this.$refs.dataForm.clearValidate()
      this.currentStep--
      this.$emit('update:stepIndex', this.currentStep)
    },
    clearValidate() {
      this.$refs.dataForm.clearValidate()
    },
    async handleToNext() {
      if (await this.validate()) {
        this.currentStep++
        this.$emit('update:stepIndex', this.currentStep)
      }
    },
    isShowed(col) {
      if (col.showFilter) {
        return col.showFilter({value: this.value, isEdit: this.isEdit})
      }
      return true
    },
    valueFilter(val, defaultValue = null) {
      if (typeof val === 'undefined') {
        return defaultValue
      }
      if (typeof val === 'function') {
        return val({
          value: this.value,
          isEdit: this.isEdit
        })
      }
      return val
    }
  }
}
</script>

<style scoped lang="scss">
.form__stepArea {
  padding-bottom: 30px;
}

.form__editor {
  margin-left: 10px;
  cursor: pointer;
}
</style>
